# Copyright (C) 2009 Martin Kirsche

from __future__ import with_statement
import os
import sys
import shutil
import socket
import urllib2

try:
    import id3
except:
    pass

from LastFm import LastFmClient


class LastFmPlayer(LastFmClient):
    
    def __init__(self):
        socket.setdefaulttimeout(20.0)
        self.waitPause = 1000.0
        self.waitError = 1000.0
        self.waitNormal = 200.0
        self.downloadFileName = None
        self.downloadTempFileName = None
        self.bufferSize = 1024*10
        self.outputToStdOut = False
        self.createId3 = False
        self.ignoreErrors = False
        self.doSkip = False
        self.doStop = False
        self.doDownload = False
        self.isPaused = True
        
        try:
            import msvcrt, os
            msvcrt.setmode(1, os.O_BINARY)
        except:
            pass
        self.__state = []
    
    def isDownloadEnabled(self):
        return self.downloadFileName is not None and self.downloadTempFileName is not None
    
    def play(self):
        self.doStop = False
        self.isPaused = False
    
    def poll(self):
        try:
            for x in self.__state: return x
            self.__state = self.__playloop()
            return self.poll()
        except:
            self.reset()
            if not self.ignoreErrors: raise
            return self.waitError
    
    def reset(self):
        self.doDownload = False
        self.doSkip = False
        self.__state = []
    
    def pause(self):
        self.isPaused = True
    
    def skip(self):
        self.doSkip = True
    
    def stop(self):
        self.doStop = True
    
    def download(self):
        self.doDownload = True
    
    def openTempFile(self, filename):
        if not self.isDownloadEnabled(): return DummyFile()
        return open(mkdir(filename), 'wb')
    
    def writeId3(self, track):
        if not self.createId3 or not self.isDownloadEnabled(): return
        id3info = id3.ID3v2()
        id3info.new_frame('TIT2').value = track.title
        id3info.new_frame('TALB').value = track.album
        id3info.new_frame('TPE1').value = track.creator
        if track.image:
            img = id3info.new_frame('APIC')
            img.image = urllib2.urlopen(track.image).read()
            img.picturetype = '\x03'
            img.mimetype = 'image/jpeg'
            img.description = track.title
        id3info.filename = self.downloadTempFileName
        id3info.save()
    
    def __playloop(self):
        while self.isPaused:
            yield self.waitPause
        while not self.doStop:
            playlist = None
            try:
                playlist = self.playlist()
            except:
                if not self.ignoreErrors: raise
            if not playlist: 
                yield self.waitError
                continue
            stationName = self.stationName
            
            for track in playlist:
                yield self.waitNormal
                try:
                    r = urllib2.urlopen(track.location)
                except:
                    if not self.ignoreErrors: raise
                    yield self.waitError
                    continue
                
                tempfile = format(self.downloadTempFileName, track)
                with self.openTempFile(tempfile) as tempFile:
                    while not self.doSkip and not self.doStop:
                        yield self.waitNormal
                        while self.isPaused: yield self.waitPause
                        data = None
                        try:
                            data = r.read(self.bufferSize)
                        except:
                            if not self.ignoreErrors: raise
                        if not data:
                            break
                        if self.isDownloadEnabled():
                            tempFile.write(data)
                        if self.outputToStdOut:
                            sys.stdout.write(data)
                            
                if self.isDownloadEnabled():
                    self.writeId3(track)
                    if not self.doSkip and self.doDownload:
                        shutil.move(tempfile,
                            mkdir(format(self.downloadFileName, track)))
                        self.doDownload = False
                
                self.doSkip = False
                if stationName != self.stationName: break
        
        yield self.waitNormal # Prevents endless loops when self.poll is called
                              # while self.doStop is True and self.isPaused is
                              # False.


def format(template, value):
    for p in value.__dict__:
        template = template.replace('{%s}' % p, unicode(value.__getattribute__(p)))
    return template

def mkdir(path):
    if not os.path.isdir(os.path.dirname(path)):
        os.mkdir(os.path.dirname(path))
    return path

class DummyFile:
    def __enter__(self): pass
    def __exit__(self, type, value, traceback): pass
